<template>
  <div :class="[noBackground ? chartNoBackground : chartBackground]">
    <div class="chart-title" ref="title" v-if="chartTitle">
      {{ chartTitle }}
    </div>
    <VChart
      ref="myChart"
      :style="{ height: height }"
      :option="option"
      :loading="loading"
      autoresize
      @click="onClick"
      @brushend="onBrushend"
      @dataZoom="onDataZoom"
    />
  </div>
</template>

<script setup>
import { ref, computed, onMounted } from 'vue'
import VChart from 'vue-echarts'
import _ from 'lodash'

// props
const props = defineProps({
  dataSource: { type: Object, default: () => ({}) },
  chartOption: { type: Object, default: () => ({}) },
  titleColor: { type: String, default: '#10e7f7' },
  titleSize: { type: String, default: '0.3rem' },
  height: { type: String, default: '100%' },
  unit: { type: String, default: '' },
  noBackground: { type: Boolean, default: false },
  enableVisualMap: { type: Boolean, default: false },
  chartTitle: { type: String, default: '' },
  logInfo: { type: String, default: '' },
  loading: { type: Boolean, default: false }
})

// emits
const emit = defineEmits(['click', 'funChartData'])

// refs
const myChart = ref(null)
const title = ref(null)

// class
const chartBackground = 'echarts-background'
const chartNoBackground = 'echarts-no-background'

// 默认配置
const defaultOption = {
  title: { x: '5%' },
  tooltip: {
    trigger: 'axis',
    textStyle: { color: '#333' },
    formatter(params) {
      let str = ''
      if (props.dataSource.xAxisType === 'time') {
        str = params[0].data[0] + '<br />'
      } else {
        str = params[0].axisValue + '<br />'
      }
      if (params[0].data.length > 0) {
        params.forEach((item) => {
          if (item.data[1]) {
            str +=
              '<span style="display:inline-block;margin-right:5px;border-radius:50%;width:10px;height:10px;background-color:' +
              item.color +
              '"></span>' +
              item.seriesName +
              '：' +
              item.data[1] +
              '<br />'
          }
        })
      } else {
        params.forEach((item) => {
          if (item.data) {
            str +=
              '<span style="display:inline-block;margin-right:5px;border-radius:50%;width:10px;height:10px;background-color:' +
              item.color +
              '"></span>' +
              item.seriesName +
              '：' +
              item.data +
              '<br />'
          }
        })
      }
      return str
    }
  },
  grid: {
    top: '12',
    left: '0',
    right: '5',
    bottom: '30',
    containLabel: true
  },
  toolbox: {
    itemSize: 20,
    feature: {
      brush: {
        type: ['rect', 'clear'],
        title: { rect: '剔野' }
      }
    },
    iconStyle: { borderColor: '#333' },
    emphasis: { iconStyle: { textFill: '#333', textAlign: 'right' } },
    left: 38,
    top: -5
  },
  brush: {
    xAxisIndex: 'all',
    brushLink: 'all',
    outOfBrush: { colorAlpha: 0.1 },
    removeOnClick: false
  },
  visualMap: {
    show: false,
    dimension: 1,
    pieces: [{ gte: 20, lte: 100, color: 'red' }],
    outOfRange: { color: '#4460fc' }
  },
  legend: {
    left: 'center',
    bottom: 5,
    itemGap: 25,
    itemWidth: 8,
    itemHeight: 8,
    show: true,
    icon: 'circle',
    textStyle: {
      color: () => {
        return _.map(props.dataSource.yAxis, (item) => item.color)
      }
    }
  },
  xAxis: {
    type: props.dataSource.xAxisType ? props.dataSource.xAxisType : 'category',
    axisLabel: {
      margin: 12,
      textStyle: { color: '#333' },
      formatter: (value) => {
        const dates = new Date(value)
        let month = dates.getMonth() + 1
        month = month < 10 ? '0' + month : month
        const date = dates.getDate() < 10 ? '0' + dates.getDate() : dates.getDate()
        const h = dates.getHours() < 10 ? '0' + dates.getHours() : dates.getHours()
        const m = dates.getMinutes() < 10 ? '0' + dates.getMinutes() : dates.getMinutes()
        const s = dates.getSeconds() < 10 ? '0' + dates.getSeconds() : dates.getSeconds()
        return dates.getFullYear() + '-' + month + '-' + date + '\n' + h + ':' + m + ':' + s
      }
    },
    axisTick: { show: false },
    axisLine: { lineStyle: { color: '#E8E8E8' } },
    splitLine: { show: false }
  },
  dataZoom: [
    {
      type: 'inside',
      show: true,
      start: 0,
      end: 100,
      minSpan: 1
    }
  ],
  yAxis: {
    splitNumber: null,
    scale: true,
    axisLine: { show: true, lineStyle: { color: '#E8E8E8' } },
    splitLine: {
      show: true,
      lineStyle: { color: '#E8E8E8', opacity: 0.5, type: 'dotted' }
    },
    axisTick: { show: false },
    axisLabel: { textStyle: { color: '#333' } }
  }
}

// 计算 option
const option = computed(() => {
  return {
    title: _.assign({}, defaultOption.title, props.chartOption.title || {}),
    tooltip: _.assign({}, defaultOption.tooltip, props.chartOption.tooltip || {}),
    grid: _.assign({}, defaultOption.grid, props.chartOption.grid || {}),
    toolbox: _.assign({}, defaultOption.toolbox, props.chartOption.toolbox, {
      show: props.dataSource.toolboxShow
    }),
    brush: _.assign({}, defaultOption.brush),
    visualMap: props.enableVisualMap
      ? _.assign({}, defaultOption.visualMap, props.chartOption.visualMap || {})
      : props.enableVisualMap,
    legend: _.assign({}, defaultOption.legend, props.chartOption.legend || {}),
    xAxis: _.assign({}, defaultOption.xAxis, props.chartOption.xAxis, {
      data: props.dataSource.xAxis
    }),
    yAxis: _.assign({}, defaultOption.yAxis, props.chartOption.yAxis || {}),
    dataZoom: _.assign([], defaultOption.dataZoom, props.chartOption.dataZoom || []),
    series: _.map(props.dataSource.yAxis, (dataItem) => {
      return {
        type: dataItem.chartType || 'line',
        symbol: dataItem.symbol || 'circle',
        smooth: dataItem.smooth !== false,
        symbolSize: dataItem.symbolSize || 8,
        showSymbol: dataItem.showSymbol || dataItem.data.length === 1,
        name: dataItem.name,
        data: dataItem.data,
        markLine: dataItem.markLine,
        sampling: 'lttb',
        itemStyle: {
          color: dataItem.color,
          borderColor: 'rgba(255,255,255,0.8)',
          borderWidth: 0
        }
      }
    })
  }
})

// 事件
function onClick(e) {
  emit('click', e)
}
function onBrushend(params) {
  // 任意形状选框选择功能
  if (params.areas && params.areas[0] && params.areas[0].coordRanges && params.areas[0].coordRanges[0]) {
    const indexArray = params.areas[0].coordRanges[0][0]
    emit('funChartData', {
      start: Math.round(indexArray[0]),
      end: Math.ceil(indexArray[1])
    })
  }
}
function onDataZoom(e) {
  // 处理滚动放大重影问题
  const dom = myChart.value?.getDom()?.firstChild?.lastChild
  if (dom && dom.getAttribute('data-zr-dom-id') === 'zr_100000') {
    dom.style.setProperty('display', 'none')
  }
}

// 设置标题样式
onMounted(() => {
  if (props.chartTitle && title.value) {
    title.value.style.setProperty('--title-color', props.titleColor)
    title.value.style.setProperty('--title-size', props.titleSize)
  }
})
</script>

<style scoped lang="less">
.echarts-background {
  font-size: 0.3rem;
  color: #10e7f7;
  width: 100%;
  height: 100%;
  background: url('~@/assets/image/chart-bg.png') no-repeat;
  background-size: 100% 100%;
}
.echarts-no-background {
  width: 100%;
  height: 100%;
}
.chart-title {
  text-align: center;
  color: var(--title-color, #10e7f7);
  font-size: var(--title-size, 0.3rem);
  line-height: 45px;
  height: 45px;
}
.chart-log {
  line-height: 20px;
  font-size: 12px;
  text-align: left;
  padding-left: 60px;
  color: #f56c6c;
}
</style>
